<?php
/**
 * 业务处理类
 */
namespace Swocloud;

use DomainException;
use Redis;
use Swoole\Server;
use Firebase\JWT\JWT;
use Swoole\Http\Request;
use Swoole\Http\Response;
use Swocloud\Supper\Arithmetic;

class Dispatcher
{
    /**
     * 
     * @var Redis|null
     */
    protected $redis = null;
    protected $jwtKey = 'swocloud';

    public function __construct($redis = null) 
    {
        $this->redis = $redis;
    }

    /**
     * 服务器注册进路由
     * @param Route $route 路由对象
     * @param Server $server 
     * @param mixed $fd 
     * @param mixed $data 
     * @return void 
     */
    public function register(Route $route, Server $server, $fd, $data)
    {
        // 获取缓存名
        $cacheKey = $route->getCacheKey($server);

        $cacheData = json_encode([
            'ip' => $data['ip'],
            'port' => $data['port'],
            'serverName' => $data['serverName']
        ]);

        // 将服务器信息写入redis
        $this->redis->sadd($cacheKey, $cacheData);

        // 开启定时器，对当前服务器进行宕机检测
        $server->tick(3000, function($timerId) use ($server, $fd, $cacheKey, $cacheData) {
            echo '宕机检测' . PHP_EOL;
            // 如果server中不存在该连接，即该连接断开
            if (!$server->exists($fd)) {
                dd($cacheData . '--宕机');
                $this->redis->srem($cacheKey, $cacheData);
                $server->clearTimer($timerId);
            }
        });
    }

    /**
     * 
     * @param Route $route 
     * @param Request $request 
     * @param Response $response 
     * @return void 
     */
    public function login(Route $route, Request $request, Response $response)
    {

        // 1. 验证账号密码是否正确
        $dataFile = file_get_contents(__DIR__ . '/./data.json');
        $userData = json_decode($dataFile, true);

        // if ($data['username'] != $userData['username'] || $data['password'] != $userData['password']) {
        //     $response->end('用户名或密码错误');
        // }

        // 此处就直接传入uid了
        $uid = $request->post['uid'] ?? $userData['uid'];
        
        // 2. 获取im服务器参数  ip:port
        $serverUrl = json_decode($this->getServerUrl($route), true);
        
        $serverUrl = $serverUrl['ip'] . ':' . $serverUrl['port'];

        // 3. JWT 生成token
        $token = $this->getToken($uid, $serverUrl);

        // 4. 发送数据给客户端
        $response->end(json_encode(['token' => $token, 'url' => $serverUrl]));
    }

    /**
     * 生成token
     * @param mixed $uid 
     * @param mixed $url 
     * @return string 
     * @throws DomainException 
     */
    protected function getToken($uid, $url)
    {
        $time = time();
        $payload = [
            'iss' => '',
            'aud' => '',
            'iat' => $time, // 签发时间
            'nbf' => $time, // 生效时间
            'exp' => $time + (60 * 60 * 24), // 过期时间
            'data' => [
                'uid' => $uid,
                'name' => 'bbt',
                'serverUrl' => $url
            ]
        ];
        
        return JWT::encode($payload, $this->jwtKey);
    }


    /**
     * 根据一定算法获取imserver
     * @param Route $route 
     * @return mixed|void 
     */
    protected function getServerUrl(Route $route)
    {
        $imServers = $this->redis->smembers($route->getCacheKey());

        // 服务器数据不为空
        if (!empty($imServers)) {
            return Arithmetic::{$route->getArithmetic()}($imServers);
        }

    }

}